Context
In this exercise we are going to study the results from a particle analysis performed on a set of SEM images of Ni nanoparticles.
To obtain these nanoparticles, we start from Si wafers on which a 5 or 10 nm layer of Ni is deposited by PVD. These wafers are then heated in an H2 atmosphere to reduce them, which provokes the formation of nanoparticles through unwetting of the Si surface. These nanoparticles are then used as catalyst for the growth of vertically aligned carbon nanotubes by PECVD. As the diameter and density of the tubes are directly related to the diameter and density of the nanoparticles, we are interested in getting a clear idea of these parameters before performing the nanotube growth.
Some Ni-covered Si wafers were prepared before the first confinement (substrates labeled as old), some were prepared in September (new substrates). Here, we are interested in seeing whether the age and thickness of the Ni layer plays a role on the nanoparticles size and density. Also, the other parameters to study are the temperature at which the unwetting is performed, as well as the duration of this reaction.
To perform this study, we prepared samples from various substrates at various temperatures and during various times. The substrates are then observed with SEM, and several pictures are taken to increase the statistics. These pictures are then analyzed with ImageJ, as shown on Figure 1.1.
In this exercise, we are going to treat the tables obtained from ImageJ: these tables contain the (x,y) positions of the particles as well as their area.
Data wrangling
- Load the packages
tidyverse, readxl, units, broom, and ggforce. We are going to getting used to work with units in this exercise, which is a very good habit to take in order to avoid many unit conversion problems. The package ggforce allows doing ggplot plots with tibbles containing units. Set the global ggplot2 theme to black and white. Also, make it so that the strip.background (background of the facets titles) is blank, and that the strip.text is bold.
- Find all csv files in the
Data_SEM folder and store them in flist.
- Read the
sample.xlsx file that contain all characteristics of the various samples, such as their temperature, substrate type, time of reaction, and store the result in samples.
- Modify the tibble
samples so that its columns are named “sample”, “T”, “time”, and “substrate”
- Using
separate(), separate the “substrate” column into “sub_thick” and “sub_age” containing the thickness and age of the substrate. Use convert = TRUE to convert the characters to integers if applicable.
- Give the columns their proper unit when applicable (refer to this example)
samples <- read_excel("Data_SEM/sample.xlsx") %>%
rename(sample = "name",
T = "Temperature (°C)",
time = "Time (minutes)",
substrate = "Substrate (nm)") %>%
separate(substrate, c("sub_thick","sub_age"), convert = TRUE) %>%
mutate(sub_thick = set_units(sub_thick,"nm"),
time = set_units(time,"min"),
T = set_units(T,"degC")
)
- Create the
readfile(filename) function that, given one of the csv files names, will:
- Determine the unit used in this file: from
filename, store the unit into the variable UNIT (that should be the string "um" or "nm"). You can use unlist(strsplit(filename,"_")) to get a vector of the elements of filename separated by a _ character.
- Read the csv file, then successively:
- Select only the X, Y and Area columns (some files have more columns) and rename them to lowercases names.
- Add the
file column containing the filename, and then separate it into 3 columns sample, number and unit
- Remove the
unit column
- Apply the corresponding units to x, y and area. You can apply a unit to a vector
x based on a string xx using set_units(x, xx, mode = "standard").
- Create a column
diameter containing the diameter of the particles.
- Test this function on 2 files with 2 different units to check that it gives the expected result.
readfile <- function(filename){
UNIT <- unlist(strsplit(filename,"_"))
UNIT <- gsub(".csv","",UNIT[length(UNIT)])
read_csv(filename) %>%
select(X,Y,Area) %>%
rename(x="X",y="Y",area="Area") %>%
mutate(file=gsub("Data_SEM/","",filename)) %>%
separate(file, c("sample","number","unit"), sep="_") %>%
select(-unit) %>%
mutate(x = set_units(x, UNIT, mode = "standard"),
y = set_units(y, UNIT, mode = "standard"),
area = set_units(area, paste0(UNIT,"*",UNIT), mode = "standard"),
diameter = sqrt(4*area/pi))
}
readfile("Data_SEM/ML16_02_um.csv")
## # A tibble: 100 x 6
## x y area sample number diameter
## [um] [um] [um^2] <chr> <chr> [um]
## 1 0.221 0.116 0.006 ML16 02 0.08740387
## 2 0.328 0.273 0.009 ML16 02 0.10704745
## 3 0.497 0.423 0.007 ML16 02 0.09440697
## 4 0.189 0.638 0.011 ML16 02 0.11834541
## 5 0.421 1.067 0.010 ML16 02 0.11283792
## 6 0.222 1.410 0.007 ML16 02 0.09440697
## 7 0.634 1.438 0.011 ML16 02 0.11834541
## 8 0.634 1.438 0.011 ML16 02 0.11834541
## 9 0.408 1.576 0.009 ML16 02 0.10704745
## 10 1.677 0.294 0.009 ML16 02 0.10704745
## # … with 90 more rows
## # A tibble: 95 x 6
## x y area sample number diameter
## [nm] [nm] [nm^2] <chr> <chr> [nm]
## 1 485.145 176.363 8177.769 ML16 04 102.04048
## 2 552.574 421.864 9433.278 ML16 04 109.59390
## 3 907.114 82.537 14149.916 ML16 04 134.22456
## 4 781.287 193.600 5123.831 ML16 04 80.77044
## 5 762.260 447.889 9433.278 ML16 04 109.59390
## 6 521.046 927.668 16118.010 ML16 04 143.25532
## 7 781.635 653.703 8008.106 ML16 04 100.97642
## 8 906.002 1081.880 9501.143 ML16 04 109.98741
## 9 869.637 1270.324 8381.365 ML16 04 103.30288
## 10 162.661 1767.427 10010.133 ML16 04 112.89507
## # … with 85 more rows
- Using
readfile() that you just defined, read all csv files and store them into a tidy tibble called particles. Do not use a for loop to do so. Join this table with the samples one. You will see that, since we attributed units to some columns, all data are automatically converted to a single unit.
LS0tCnRpdGxlIDogIlIgRXhlcmNpc2VzIC0gUGFydGljbGUgYW5hbHlzaXMgZnJvbSBTRU0gaW1hZ2VzIgpkYXRlICA6ICJgciBTeXMuRGF0ZSgpYCIKb3V0cHV0OiAKICAgIGJvb2tkb3duOjpodG1sX2RvY3VtZW50MjoKICAgICAgICB0b2MgICAgICAgICAgICA6IFRSVUUKICAgICAgICB0b2NfZmxvYXQgICAgICA6IFRSVUUKICAgICAgICB0b2NfZGVwdGggICAgICA6IDQKICAgICAgICBoaWdobGlnaHQgICAgICA6IHRhbmdvCiAgICAgICAgbnVtYmVyX3NlY3Rpb25zOiBUUlVFCiAgICAgICAgY29kZV9mb2xkaW5nICAgOiBoaWRlCiAgICAgICAgY29kZV9kb3dubG9hZCAgOiBUUlVFCnBhcmFtczogCiAgICBzb2x1dGlvbjoKICAgICAgICB2YWx1ZTogVFJVRQotLS0KCiMgQ29udGV4dAoKSW4gdGhpcyBleGVyY2lzZSB3ZSBhcmUgZ29pbmcgdG8gc3R1ZHkgdGhlIHJlc3VsdHMgZnJvbSBhIHBhcnRpY2xlIGFuYWx5c2lzIHBlcmZvcm1lZCBvbiBhIHNldCBvZiBTRU0gaW1hZ2VzIG9mIE5pIG5hbm9wYXJ0aWNsZXMuIAoKVG8gb2J0YWluIHRoZXNlIG5hbm9wYXJ0aWNsZXMsIHdlIHN0YXJ0IGZyb20gU2kgd2FmZXJzIG9uIHdoaWNoIGEgNSBvciAxMCBubSBsYXllciBvZiBOaSBpcyBkZXBvc2l0ZWQgYnkgUFZELiBUaGVzZSB3YWZlcnMgYXJlIHRoZW4gaGVhdGVkIGluIGFuIEh+Mn4gYXRtb3NwaGVyZSB0byByZWR1Y2UgdGhlbSwgd2hpY2ggcHJvdm9rZXMgdGhlIGZvcm1hdGlvbiBvZiBuYW5vcGFydGljbGVzIHRocm91Z2ggdW53ZXR0aW5nIG9mIHRoZSBTaSBzdXJmYWNlLiBUaGVzZSBuYW5vcGFydGljbGVzIGFyZSB0aGVuIHVzZWQgYXMgY2F0YWx5c3QgZm9yIHRoZSBncm93dGggb2YgdmVydGljYWxseSBhbGlnbmVkIGNhcmJvbiBuYW5vdHViZXMgYnkgUEVDVkQuIEFzIHRoZSBkaWFtZXRlciBhbmQgZGVuc2l0eSBvZiB0aGUgdHViZXMgYXJlIGRpcmVjdGx5IHJlbGF0ZWQgdG8gdGhlIGRpYW1ldGVyIGFuZCBkZW5zaXR5IG9mIHRoZSBuYW5vcGFydGljbGVzLCB3ZSBhcmUgaW50ZXJlc3RlZCBpbiBnZXR0aW5nIGEgY2xlYXIgaWRlYSBvZiB0aGVzZSBwYXJhbWV0ZXJzIGJlZm9yZSBwZXJmb3JtaW5nIHRoZSBuYW5vdHViZSBncm93dGguCgpTb21lIE5pLWNvdmVyZWQgU2kgd2FmZXJzIHdlcmUgcHJlcGFyZWQgYmVmb3JlIHRoZSBmaXJzdCBjb25maW5lbWVudCAoc3Vic3RyYXRlcyBsYWJlbGVkIGFzIGBvbGRgKSwgc29tZSB3ZXJlIHByZXBhcmVkIGluIFNlcHRlbWJlciAoYG5ld2Agc3Vic3RyYXRlcykuIEhlcmUsIHdlIGFyZSBpbnRlcmVzdGVkIGluIHNlZWluZyB3aGV0aGVyIHRoZSBhZ2UgYW5kIHRoaWNrbmVzcyBvZiB0aGUgTmkgbGF5ZXIgcGxheXMgYSByb2xlIG9uIHRoZSBuYW5vcGFydGljbGVzIHNpemUgYW5kIGRlbnNpdHkuIEFsc28sIHRoZSBvdGhlciBwYXJhbWV0ZXJzIHRvIHN0dWR5IGFyZSB0aGUgdGVtcGVyYXR1cmUgYXQgd2hpY2ggdGhlIHVud2V0dGluZyBpcyBwZXJmb3JtZWQsIGFzIHdlbGwgYXMgdGhlIGR1cmF0aW9uIG9mIHRoaXMgcmVhY3Rpb24uCgpUbyBwZXJmb3JtIHRoaXMgc3R1ZHksIHdlIHByZXBhcmVkIHNhbXBsZXMgZnJvbSB2YXJpb3VzIHN1YnN0cmF0ZXMgYXQgdmFyaW91cyB0ZW1wZXJhdHVyZXMgYW5kIGR1cmluZyB2YXJpb3VzIHRpbWVzLiBUaGUgc3Vic3RyYXRlcyBhcmUgdGhlbiBvYnNlcnZlZCB3aXRoIFNFTSwgYW5kIHNldmVyYWwgcGljdHVyZXMgYXJlIHRha2VuIHRvIGluY3JlYXNlIHRoZSBzdGF0aXN0aWNzLiBUaGVzZSBwaWN0dXJlcyBhcmUgdGhlbiBhbmFseXplZCB3aXRoIFtJbWFnZUpdKGh0dHBzOi8vaW1hZ2VqLm5ldC9XZWxjb21lKSwgYXMgc2hvd24gb24gRmlndXJlIFxAcmVmKGZpZzpTRU1pbWFnZXMpLiAKCmBgYHtyIFNFTWltYWdlcywgZWNobz1GQUxTRSwgbWVzc2FnZT1GQUxTRSwgZmlnLmNhcD0iVHlwaWNhbCBTRU0gaW1hZ2Ugb2YgTmkgbmFub3BhcnRpY2xlczogZnJvbSB0aGUgcmF3IGltYWdlIHRvIHBhcnRpY2xlIGFuYWx5c2lzIiwgZmlnLmFsaWduPSJjZW50ZXIiLCBvdXQud2lkdGg9IjMzJSIsIGZpZy5zaG93PSdob2xkJ30KbXlpbWFnZXMgPC0gYygiRGF0YV9TRU0vTUwyNl8wMS5wbmciLCAiRGF0YV9TRU0vTUwyNl8wMS10aHJlc2hvbGQucG5nIiwgIkRhdGFfU0VNL01MMjZfMDEtcGFydGljbGVzLnBuZyIpCmtuaXRyOjppbmNsdWRlX2dyYXBoaWNzKG15aW1hZ2VzKQpgYGAKCkluIHRoaXMgZXhlcmNpc2UsIHdlIGFyZSBnb2luZyB0byB0cmVhdCB0aGUgdGFibGVzIG9idGFpbmVkIGZyb20gSW1hZ2VKOiB0aGVzZSB0YWJsZXMgY29udGFpbiB0aGUgKHgseSkgcG9zaXRpb25zIG9mIHRoZSBwYXJ0aWNsZXMgYXMgd2VsbCBhcyB0aGVpciBhcmVhLgoKIyBEYXRhIHdyYW5nbGluZwoKLSBMb2FkIHRoZSBwYWNrYWdlcyBgdGlkeXZlcnNlYCwgYHJlYWR4bGAsIGB1bml0c2AsIGBicm9vbWAsIGFuZCBgZ2dmb3JjZWAuIFdlIGFyZSBnb2luZyB0byBnZXR0aW5nIHVzZWQgdG8gd29yayB3aXRoIHVuaXRzIGluIHRoaXMgZXhlcmNpc2UsIHdoaWNoIGlzIGEgdmVyeSBnb29kIGhhYml0IHRvIHRha2UgaW4gb3JkZXIgdG8gYXZvaWQgbWFueSB1bml0IGNvbnZlcnNpb24gcHJvYmxlbXMuIFRoZSBwYWNrYWdlIGBnZ2ZvcmNlYCBhbGxvd3MgZG9pbmcgYGdncGxvdGAgcGxvdHMgd2l0aCB0aWJibGVzIGNvbnRhaW5pbmcgdW5pdHMuIFNldCB0aGUgZ2xvYmFsIGBnZ3Bsb3QyYCB0aGVtZSB0byBibGFjayBhbmQgd2hpdGUuIEFsc28sIG1ha2UgaXQgc28gdGhhdCB0aGUgYHN0cmlwLmJhY2tncm91bmRgIChiYWNrZ3JvdW5kIG9mIHRoZSBmYWNldHMgdGl0bGVzKSBpcyBibGFuaywgYW5kIHRoYXQgdGhlIGBzdHJpcC50ZXh0YCBpcyBib2xkLgoKYGBge3IgaW5jbHVkZT1wYXJhbXMkc29sdXRpb24sIHdhcm5pbmcgPSBGQUxTRSwgbWVzc2FnZT1GQUxTRX0KbGlicmFyeSh0aWR5dmVyc2UpCmxpYnJhcnkocmVhZHhsKQpsaWJyYXJ5KHVuaXRzKQpsaWJyYXJ5KGdnZm9yY2UpCmxpYnJhcnkoYnJvb20pCnRoZW1lX3NldCh0aGVtZV9idygpKwogICAgICAgICAgdGhlbWUoc3RyaXAuYmFja2dyb3VuZCA9IGVsZW1lbnRfYmxhbmsoKSwKICAgICAgICAgICAgICAgIHN0cmlwLnRleHQ9ZWxlbWVudF90ZXh0KGZhY2UgPSAiYm9sZCIsIHNpemU9MTQpCiAgICAgICAgICAgICAgICApKQpgYGAKCi0gRmluZCBhbGwgY3N2IGZpbGVzIGluIHRoZSBgRGF0YV9TRU1gIGZvbGRlciBhbmQgc3RvcmUgdGhlbSBpbiBgZmxpc3RgLgoKYGBge3IgaW5jbHVkZT1wYXJhbXMkc29sdXRpb24sIHdhcm5pbmcgPSBGQUxTRSwgbWVzc2FnZT1GQUxTRX0KZmxpc3QgPC0gbGlzdC5maWxlcyhwYXRoPSJEYXRhX1NFTSIsIHBhdHRlcm49Ii5jc3YiKQpgYGAKCi0gUmVhZCB0aGUgYHNhbXBsZS54bHN4YCBmaWxlIHRoYXQgY29udGFpbiBhbGwgY2hhcmFjdGVyaXN0aWNzIG9mIHRoZSB2YXJpb3VzIHNhbXBsZXMsIHN1Y2ggYXMgdGhlaXIgdGVtcGVyYXR1cmUsIHN1YnN0cmF0ZSB0eXBlLCB0aW1lIG9mIHJlYWN0aW9uLCBhbmQgc3RvcmUgdGhlIHJlc3VsdCBpbiBgc2FtcGxlc2AuIAogICAgLSBNb2RpZnkgdGhlIHRpYmJsZSBgc2FtcGxlc2Agc28gdGhhdCBpdHMgY29sdW1ucyBhcmUgbmFtZWQgInNhbXBsZSIsICJUIiwgInRpbWUiLCBhbmQgInN1YnN0cmF0ZSIKICAgIC0gVXNpbmcgYHNlcGFyYXRlKClgey5SfSwgc2VwYXJhdGUgdGhlICJzdWJzdHJhdGUiIGNvbHVtbiBpbnRvICJzdWJfdGhpY2siIGFuZCAic3ViX2FnZSIgY29udGFpbmluZyB0aGUgdGhpY2tuZXNzIGFuZCBhZ2Ugb2YgdGhlIHN1YnN0cmF0ZS4gVXNlIGBjb252ZXJ0ID0gVFJVRWAgdG8gY29udmVydCB0aGUgY2hhcmFjdGVycyB0byBpbnRlZ2VycyBpZiBhcHBsaWNhYmxlLgogICAgLSBHaXZlIHRoZSBjb2x1bW5zIHRoZWlyIHByb3BlciB1bml0IHdoZW4gYXBwbGljYWJsZSAocmVmZXIgdG8gW3RoaXMgZXhhbXBsZV0oaHR0cHM6Ly9sbWkuY25ycy5mci9yL3dvcmtpbmctd2l0aC11bml0cy5odG1sKSkKCmBgYHtyIGluY2x1ZGU9cGFyYW1zJHNvbHV0aW9uLCB3YXJuaW5nID0gRkFMU0UsIG1lc3NhZ2U9RkFMU0V9CnNhbXBsZXMgPC0gcmVhZF9leGNlbCgiRGF0YV9TRU0vc2FtcGxlLnhsc3giKSAlPiUgCiAgICByZW5hbWUoc2FtcGxlICAgID0gIm5hbWUiLAogICAgICAgICAgIFQgICAgICAgICA9ICJUZW1wZXJhdHVyZSAowrBDKSIsCiAgICAgICAgICAgdGltZSAgICAgID0gIlRpbWUgKG1pbnV0ZXMpIiwKICAgICAgICAgICBzdWJzdHJhdGUgPSAiU3Vic3RyYXRlIChubSkiKSAlPiUgCiAgICBzZXBhcmF0ZShzdWJzdHJhdGUsIGMoInN1Yl90aGljayIsInN1Yl9hZ2UiKSwgY29udmVydCA9IFRSVUUpICU+JSAKICAgIG11dGF0ZShzdWJfdGhpY2sgPSBzZXRfdW5pdHMoc3ViX3RoaWNrLCJubSIpLAogICAgICAgICAgIHRpbWUgICAgICA9IHNldF91bml0cyh0aW1lLCJtaW4iKSwKICAgICAgICAgICBUICAgICAgICAgPSBzZXRfdW5pdHMoVCwiZGVnQyIpCiAgICAgICAgICAgKQpgYGAKCi0gQ3JlYXRlIHRoZSBgcmVhZGZpbGUoZmlsZW5hbWUpYHsuUn0gZnVuY3Rpb24gdGhhdCwgZ2l2ZW4gb25lIG9mIHRoZSBjc3YgZmlsZXMgbmFtZXMsIHdpbGw6CiAgICAtIERldGVybWluZSB0aGUgdW5pdCB1c2VkIGluIHRoaXMgZmlsZTogZnJvbSBgZmlsZW5hbWVgLCBzdG9yZSB0aGUgdW5pdCBpbnRvIHRoZSB2YXJpYWJsZSBgVU5JVGAgKHRoYXQgc2hvdWxkIGJlIHRoZSBzdHJpbmcgYCJ1bSJgIG9yIGAibm0iYCkuIFlvdSBjYW4gdXNlIGB1bmxpc3Qoc3Ryc3BsaXQoZmlsZW5hbWUsIl8iKSlgey5SfSB0byBnZXQgYSB2ZWN0b3Igb2YgdGhlIGVsZW1lbnRzIG9mIGBmaWxlbmFtZWAgc2VwYXJhdGVkIGJ5IGEgYF9gIGNoYXJhY3Rlci4KICAgIC0gUmVhZCB0aGUgY3N2IGZpbGUsIHRoZW4gc3VjY2Vzc2l2ZWx5OgogICAgLSBTZWxlY3Qgb25seSB0aGUgWCwgWSBhbmQgQXJlYSBjb2x1bW5zIChzb21lIGZpbGVzIGhhdmUgbW9yZSBjb2x1bW5zKSBhbmQgcmVuYW1lIHRoZW0gdG8gbG93ZXJjYXNlcyBuYW1lcy4KICAgIC0gQWRkIHRoZSBgZmlsZWAgY29sdW1uIGNvbnRhaW5pbmcgdGhlIGZpbGVuYW1lLCBhbmQgdGhlbiBzZXBhcmF0ZSBpdCBpbnRvIDMgY29sdW1ucyBgc2FtcGxlYCwgYG51bWJlcmAgYW5kIGB1bml0YAogICAgLSBSZW1vdmUgdGhlIGB1bml0YCBjb2x1bW4KICAgIC0gQXBwbHkgdGhlIGNvcnJlc3BvbmRpbmcgdW5pdHMgdG8geCwgeSBhbmQgYXJlYS4gWW91IGNhbiBhcHBseSBhIHVuaXQgdG8gYSB2ZWN0b3IgYHhgIGJhc2VkIG9uIGEgKipzdHJpbmcqKiBgeHhgIHVzaW5nIGBzZXRfdW5pdHMoeCwgeHgsIG1vZGUgPSAic3RhbmRhcmQiKWB7LlJ9LgogICAgLSBDcmVhdGUgYSBjb2x1bW4gYGRpYW1ldGVyYCBjb250YWluaW5nIHRoZSBkaWFtZXRlciBvZiB0aGUgcGFydGljbGVzLgotIFRlc3QgdGhpcyBmdW5jdGlvbiBvbiAyIGZpbGVzIHdpdGggMiBkaWZmZXJlbnQgdW5pdHMgdG8gY2hlY2sgdGhhdCBpdCBnaXZlcyB0aGUgZXhwZWN0ZWQgcmVzdWx0LgoKYGBge3IgaW5jbHVkZT1wYXJhbXMkc29sdXRpb24sIHdhcm5pbmcgPSBGQUxTRSwgbWVzc2FnZT1GQUxTRX0KcmVhZGZpbGUgPC0gZnVuY3Rpb24oZmlsZW5hbWUpewogICAgVU5JVCA8LSB1bmxpc3Qoc3Ryc3BsaXQoZmlsZW5hbWUsIl8iKSkKICAgIFVOSVQgPC0gZ3N1YigiLmNzdiIsIiIsVU5JVFtsZW5ndGgoVU5JVCldKQogICAgcmVhZF9jc3YoZmlsZW5hbWUpICU+JSAKICAgICAgICBzZWxlY3QoWCxZLEFyZWEpICU+JSAKICAgICAgICByZW5hbWUoeD0iWCIseT0iWSIsYXJlYT0iQXJlYSIpICU+JSAKICAgICAgICBtdXRhdGUoZmlsZT1nc3ViKCJEYXRhX1NFTS8iLCIiLGZpbGVuYW1lKSkgJT4lIAogICAgICAgIHNlcGFyYXRlKGZpbGUsIGMoInNhbXBsZSIsIm51bWJlciIsInVuaXQiKSwgc2VwPSJfIikgJT4lIAogICAgICAgIHNlbGVjdCgtdW5pdCkgJT4lIAogICAgICAgIG11dGF0ZSh4ICAgICAgICA9IHNldF91bml0cyh4LCBVTklULCBtb2RlID0gInN0YW5kYXJkIiksCiAgICAgICAgICAgICAgIHkgICAgICAgID0gc2V0X3VuaXRzKHksIFVOSVQsIG1vZGUgPSAic3RhbmRhcmQiKSwKICAgICAgICAgICAgICAgYXJlYSAgICAgPSBzZXRfdW5pdHMoYXJlYSwgcGFzdGUwKFVOSVQsIioiLFVOSVQpLCBtb2RlID0gInN0YW5kYXJkIiksCiAgICAgICAgICAgICAgIGRpYW1ldGVyID0gc3FydCg0KmFyZWEvcGkpKQp9CnJlYWRmaWxlKCJEYXRhX1NFTS9NTDE2XzAyX3VtLmNzdiIpCnJlYWRmaWxlKCJEYXRhX1NFTS9NTDE2XzA0X25tLmNzdiIpCmBgYAoKLSBVc2luZyBgcmVhZGZpbGUoKWB7LlJ9IHRoYXQgeW91IGp1c3QgZGVmaW5lZCwgcmVhZCBhbGwgY3N2IGZpbGVzIGFuZCBzdG9yZSB0aGVtIGludG8gYSB0aWR5IHRpYmJsZSBjYWxsZWQgYHBhcnRpY2xlc2AuICoqRG8gbm90IHVzZSBhIGZvciBsb29wIHRvIGRvIHNvLioqIEpvaW4gdGhpcyB0YWJsZSB3aXRoIHRoZSBgc2FtcGxlc2Agb25lLiBZb3Ugd2lsbCBzZWUgdGhhdCwgc2luY2Ugd2UgYXR0cmlidXRlZCB1bml0cyB0byBzb21lIGNvbHVtbnMsIGFsbCBkYXRhIGFyZSBhdXRvbWF0aWNhbGx5IGNvbnZlcnRlZCB0byBhIHNpbmdsZSB1bml0LgoKYGBge3IgaW5jbHVkZT1wYXJhbXMkc29sdXRpb24sIHdhcm5pbmcgPSBGQUxTRSwgbWVzc2FnZT1GQUxTRX0KcGFydGljbGVzIDwtIHRpYmJsZShmaWxlPWZsaXN0KSAlPiUgCiAgICBtdXRhdGUoZGF0YSA9IG1hcChmaWxlLCB+cmVhZGZpbGUoZmlsZS5wYXRoKCJEYXRhX1NFTSIsLikpKSkgJT4lIAogICAgdW5uZXN0KGRhdGEpICU+JSAKICAgIGlubmVyX2pvaW4oc2FtcGxlcykKYGBgCgojIFBsb3R0aW5nIGFuZCBhbmFseXNpcwoKIyMgU2l6ZSBhbmFseXNpcwoKLSBOb3csIHBsb3QgdGhlIGhpc3RvZ3JhbSBvZiBhbGwgcGFydGljbGUgZGlhbWV0ZXJzLCB3aXRoIGEgZmlsbCBjb2xvciBkZXBlbmRpbmcgb24gdGhlIHRpbWUgKHlvdSBuZWVkIHRvIGNvbnZlcnQgdGltZSB0byBhIGZhY3RvciksIGFuZCB3aXRoIGEgZ3JpZCBzaG93aW5nIHN1YnN0cmF0ZSBhZ2UgdnMgc3Vic3RyYXRlIHRoaWNrbmVzcyAodGhpY2tuZXNzIG9uIHRoZSBjb2x1bW5zKS4gUHV0IHRoZSBsZWdlbmQgb24gdG9wIG9mIHRoZSBncmFwaCwgYW5kIGFkZCBzb21lIHRyYW5zcGFyZW5jeSB0byB5b3VyIGNvbG9ycy4KLSBJbiBmYWN0LCBJIHVzdWFsbHkgcHJlZmVyIHRvIHBsb3QgaXQgdXNpbmcgYGdlb21fZGVuc2l0eSgpYHsuUn0gd2hpY2ggaXMgYmFzaWNhbGx5IGFuIGhpc3RvZ3JhbSBjb252b2x1dGVkIHdpdGggYSBHYXVzc2lhbiBkaXN0cmlidXRpb24gb2YgYmFuZHdpZHRoIGBid2AuIFRoaXMgYWxsb3dzIGZvciBzbW9vdGhlciBncmFwaHMuIE1ha2UgdGhpcyBwbG90IGFuZCBwbGF5IHdpdGggdGhlIGBid2AgcGFyYW1ldGVyLgotIENvbnZlcnQgLS0gKndpdGggZ2dwbG90KiAtLSB0aGUgdW5pdCBvZiB0aGUgcGFydGljbGUgZGlhbWV0ZXJzIHRvIG5hbm9tZXRlcnMgb3IgYW55IG90aGVyIHVuaXQgeW91IHdhbnQuCgpgYGB7ciBpbmNsdWRlPXBhcmFtcyRzb2x1dGlvbiwgd2FybmluZyA9IEZBTFNFLCBtZXNzYWdlPUZBTFNFfQpwYXJ0aWNsZXMgJT4lIAogICAgZ2dwbG90KGFlcyh4PWRpYW1ldGVyLCBmaWxsPWZhY3Rvcih0aW1lKSkpKwogICAgICAgIGdlb21fZGVuc2l0eShhbHBoYT0uNSwgY29sb3I9TkEsIGJ3PTQpKwogICAgICAgIGxhYnMoeCAgICA9ICJgUGFydGljbGUgRGlhbWV0ZXJgIiwKICAgICAgICAgICAgIHkgICAgPSAiRGVuc2l0eSBbYXJiLiB1bml0c10iLAogICAgICAgICAgICAgZmlsbCA9ICJUaW1lIFttaW5dIikrCiAgICAgICAgZmFjZXRfZ3JpZChzdWJfYWdlfnN1Yl90aGljaywgc2NhbGVzPSJmcmVlX3kiKSsKICAgICAgICB0aGVtZShsZWdlbmQucG9zaXRpb24gPSAidG9wIikrCiAgICAgICAgc2NhbGVfeF91bml0KHVuaXQ9Im5tIikKYGBgCgotIE5vdywgc3RvcmUgaW4gYHBhcnRpY2xlc19hdmVgIHRoZSBhdmVyYWdlIHBhcnRpY2xlIGRpYW1ldGVyIGFuZCBpdHMgc3RhbmRhcmQgZGV2aWF0aW9uIHBlciBzdWJzdHJhdGUgdGhpY2tuZXNzIGFuZCBhZ2UsIHRpbWUgYW5kIHRlbXBlcmF0dXJlIG9mIHJlYWN0aW9uLiBZb3Ugd2lsbCBub3RlIHRoYXQgYG1lYW4oKWB7LlJ9IGtlZXBzIHRoZSB1bml0IG9mIHZlY3RvcnMgd2hpbGUgYHNkKClgey5SfSBsb3NlcyBpdC4gTWFrZSBzdXJlIHRoYXQgdGhlIHN0YW5kYXJkIGRldmlhdGlvbiBjb2x1bW4gaGFzIHRoZSBwcm9wZXIgdW5pdCAodXNlIGB1bml0cyhhKSA8LSB1bml0cyhiKWB7LlJ9KS4KCmBgYHtyIGluY2x1ZGU9cGFyYW1zJHNvbHV0aW9uLCB3YXJuaW5nID0gRkFMU0UsIG1lc3NhZ2U9RkFMU0V9CnBhcnRpY2xlc19hdmUgPC0gcGFydGljbGVzICU+JSAKICAgIGdyb3VwX2J5KHN1Yl90aGljaywgc3ViX2FnZSwgdGltZSwgVCkgJT4lIAogICAgc3VtbWFyaXNlKGRpYW0gICA9IG1lYW4oZGlhbWV0ZXIpLAogICAgICAgICAgICAgIHNkZGlhbSA9IHNkKGRpYW1ldGVyKQogICAgICAgICAgICAgICkKdW5pdHMocGFydGljbGVzX2F2ZSRzZGRpYW0pIDwtIHVuaXRzKHBhcnRpY2xlc19hdmUkZGlhbSkKYGBgCgotIFBsb3QgdGhlIGF2ZXJhZ2UgZGlhbWV0ZXIgZXZvbHV0aW9uIHdpdGggcmVhY3Rpb24gdGltZSwgd2l0aCBhIGNvbG9yIHBlciBzdWJzdHJhdGUgdGhpY2tuZXNzLCBhbmQgb24gYSBncmlkIHNob3dpbmcgc3Vic3RyYXRlIGFnZSB2cyB0ZW1wZXJhdHVyZS4KICAgIC0gRG9uJ3QgZm9yZ2V0IHRvIGFkZCBlcnJvciBiYXJzIGNvcnJlc3BvbmRpbmcgdG8gdGhlIHN0YW5kYXJkIGVycm9yIG9mIHRoZSBkaWFtZXRlcnMgZGlzdHJpYnV0aW9uLgogICAgLSBBZGQgYSBsaW5lIHNob3dpbmcgYSBsaW5lYXIgZml0IGZvciBhbGwgZ3JvdXBzLiAKICAgIC0gTWFrZSBzdXJlIGJvdGggcGxvdCBheGVzIGdvIHRvIDAuIAogICAgLSBQdXQgdGhlIGxlZ2VuZCBvbiB0b3AuCiAgICAtIERlZmluZSBuaWNlIGF4aXMgbGFiZWxzICh3aXRoIHNlbnRlbmNlcyBpbnN0ZWFkIG9mIGNvbHVtbiBuYW1lcykuIEluIGNhc2UgYSBjb2x1bW4gaGFzIGEgdW5pdCB0aGF0IHdhcyBhdHRyaWJ1dGVkLCBpdCB3aWxsIHJldHVybiBhbiBlcnJvciBpbiBjYXNlIHRoZSBheGlzIGxhYmVsIHlvdSB3YW50IHRvIGdpdmUgY29udGFpbnMgd2hpdGUgc3BhY2VzLiBZb3Ugd2lsbCB0aHVzIG5lZWQgdG8gdXNlIGJhY2t0aWNrcywgbGlrZSBzbzogYGAiYFR3byB3b3Jkc2AiYGAKCmBgYHtyIGluY2x1ZGU9cGFyYW1zJHNvbHV0aW9uLCB3YXJuaW5nID0gRkFMU0UsIG1lc3NhZ2U9RkFMU0V9CnBhcnRpY2xlc19hdmUgJT4lIAogICAgZ2dwbG90KGFlcyh4PXRpbWUsIHk9ZGlhbSwgY29sb3I9ZmFjdG9yKHN1Yl90aGljaykpKSsKICAgICAgICBnZW9tX3BvaW50KGFscGhhPS41KSsKICAgICAgICBleHBhbmRfbGltaXRzKHggPSAwLCB5PTApKwogICAgICAgIGdlb21fZXJyb3JiYXIoYWVzKHltaW49ZGlhbS1zZGRpYW0seW1heD1kaWFtK3NkZGlhbSksIHdpZHRoPS4yKSsKICAgICAgICBnZW9tX3Ntb290aChtZXRob2Q9ImxtIiwgc2U9RkFMU0UsICkrCiAgICAgICAgZmFjZXRfZ3JpZChUfnN1Yl9hZ2UpKwogICAgICAgIGxhYnMoeCAgICAgPSAiVGltZSIsCiAgICAgICAgICAgICB5ICAgICA9ICJgQXZlcmFnZSBwYXJ0aWNsZSBkaWFtZXRlcmAiLAogICAgICAgICAgICAgY29sb3IgPSAiU3Vic3RyYXRlIHRoaWNrbmVzcyIpKwogICAgICAgIHRoZW1lKGxlZ2VuZC5wb3NpdGlvbiA9ICJ0b3AiKSsKICAgICAgICBzY2FsZV95X3VuaXQodW5pdD0ibm0iKQpgYGAKCi0gVXNpbmcgYGJyb29tYCBkaXNwbGF5IHRoZSBzbG9wZXMgYW5kIGludGVyY2VwdCBvZiBhbGwgbGluZWFyIGZpdHMsICoqd2l0aG91dCB1c2luZyBhIGZvciBsb29wKiouIFRoaXMgZG9lc24ndCB3b3JrIHdlbGwgd2l0aCB1bml0cywgc28gcHJpb3IgdG8gZG9pbmcgdGhlIGZpdCwgcmVtb3ZlIHRoZSB1bml0cyBvZiB5b3VyIHRpbWUgYW5kIGRpYW1ldGVyIGNvbHVtbnMgdXNpbmcgYGFzLnZlY3RvcigpYHsuUn0uCgpgYGB7ciBpbmNsdWRlPXBhcmFtcyRzb2x1dGlvbiwgd2FybmluZyA9IEZBTFNFLCBtZXNzYWdlPUZBTFNFfQpwYXJ0aWNsZXNfYXZlICU+JSAKICAgIG11dGF0ZShkaWFtICAgPSBhcy52ZWN0b3Ioc2V0X3VuaXRzKGRpYW0sIm5tIikpLAogICAgICAgICAgIHNkZGlhbSA9IGFzLnZlY3RvcihzZXRfdW5pdHMoc2RkaWFtLCJubSIpKSwKICAgICAgICAgICB0aW1lICAgPSBhcy52ZWN0b3IodGltZSkKICAgICAgICAgICApICU+JSAKICAgIG5lc3QoZGF0YT0tYyhzdWJfdGhpY2ssc3ViX2FnZSxUKSkgJT4lIAogICAgbXV0YXRlKGZpdCAgICA9IG1hcChkYXRhLCB+bG0oZGF0YT0uLCBkaWFtfnRpbWUsIHdlaWdodHMgPSAxL3NkZGlhbSkpLAogICAgICAgICAgIHRpZGllZCA9IG1hcChmaXQsIHRpZHkpKSAlPiUgCiAgICB1bm5lc3QodGlkaWVkKSAlPiUgCiAgICBzZWxlY3Qoc3ViX3RoaWNrLHN1Yl9hZ2UsVCx0ZXJtLGVzdGltYXRlKQpgYGAKCiMjIERlbnNpdHkgYW5kIG9yZGVyaW5nIGFuYWx5c2lzCgotIE5vdyB3ZSB3YW50IHRvIHNlZSB0aGUgZXZvbHV0aW9uIG9mIHRoZSBkZW5zaXR5IG9mIHBhcnRpY2xlcyBhbmQgdGhlaXIgb3JkZXJpbmcuIE9uZSB3YXkgb2YgZG9pbmcgdGhpcyBpcyB0byBsb29rIGF0IHRoZSAqRyhyKSogZGlzdHJpYnV0aW9uLCAqaS5lLiogdGhlIHByb2JhYmlsaXR5IHRvIGZpbmQgYSBwYXJ0aWNsZSBpbiAqciogaWYgb25lIGlzIGluIDAuIEkgcHJvdmlkZSBoZXJlIGJlbG93IHRoZSBmdW5jdGlvbiBgZ29mcih4LHksZHIsUm1heClgey5SfSB0aGF0IGNvbXB1dGVzIGl0IGJldHdlZW4gYDBgIGFuZCBgUm1heGAgd2l0aCBhIHN0ZXAgYGRyYCwgcHJvdmlkZWQgdGhlICh4LHkpIHBvc2l0aW9ucyBvZiBwYXJ0aWNsZXMuCgpgYGB7ciBpbmNsdWRlPVRSVUUsIHdhcm5pbmcgPSBGQUxTRSwgbWVzc2FnZT1GQUxTRX0KZ29mciA8LSBmdW5jdGlvbih4LCB5LCBkcj0uMiwgUm1heD0xMCl7CiAgICAjIE1ha2Ugc3VyZSB1bml0cyBhcmUgdW5pZm9ybSBiZWZvcmUgdXNpbmcgZGlzdCgpCiAgICB1bml0cyh5KSA8LSB1bml0cyh4KSAKICAgICMgZHIgYW5kIFJtYXggYXJlIHVuaXRsZXNzIGJ1dCBzaG91bGQgYmUgZ2l2ZW4gaW4gdGhlIHNhbWUgdW5pdHMgYXMgeAogICAgZHIgICA8LSBhcy52ZWN0b3IoZHIpCiAgICBSbWF4IDwtIGFzLnZlY3RvcihSbWF4KQogICAgIyBHZXQgYSB2ZWN0b3Igb2YgYWxsIEV1Y2xpZGlhbiBkaXN0YW5jZXMKICAgIGRkICAgPC0gYXMudmVjdG9yKGRpc3QodGliYmxlOjp0aWJibGUoeCx5KSkpCiAgICAjIE1ha2UgYSBoaXN0b2dyYW0gb3V0IG9mIGl0CiAgICBkZC5oaXN0IDwtIGhpc3QoZGQsIAogICAgICAgICAgICAgICAgICAgIGJyZWFrcz1zZXEoMCwgbWF4KGRkKStkciwgYnk9ZHIpLAogICAgICAgICAgICAgICAgICAgIHBsb3Q9RkFMU0UpCiAgICAjIEdldCB0aGUgciB2YWx1ZXMKICAgIHIgPC0gZGQuaGlzdCRtaWRzCiAgICAjIENvbXB1dGUgdGhlIG5vcm1hbGl6YXRpb24gYnkgdGhlIHN1cmZhY2Ugb2YgdGhlIAogICAgIyByaW5nIG9mIHJhZGl1cyByIGFuZCB0aGlja25lc3MgZHIKICAgIHJsbyAgPC0gciAtIGRyLzIKICAgIHJ1cCAgPC0gciArIGRyLzIKICAgIHJpbmcgPC0gcGkqKHJ1cF4yIC0gcmxvXjIpCiAgICAjIFJldHVybiB0aGUgdGliYmxlIGNvbnRhaW5pbmcgciBhbmQgRyhyKSB3aXRoIHRoZSBzYW1lIHVuaXQgYXMgeAogICAgIyBPbmx5IGRhdGEgZm9yIHI8Um1heCBpcyB3YW50ZWQsIGFuZCB3ZSByZW1vdmUgdGhlIGZpcnN0IGVsZW1lbnQgdG9vCiAgICBkIDwtIHRpYmJsZTo6dGliYmxlKFIgICAgPSByW3I8Um1heF0sIAogICAgICAgICAgICAgICAgICAgICAgICBHb2ZSID0gZGQuaGlzdCRjb3VudHNbcjxSbWF4XS9yaW5nW3I8Um1heF0pICU+JSAKICAgICAgICAgICAgcmVuYW1lKHI9IlIiLGdvZnI9IkdvZlIiKQogICAgdW5pdHMoZCRyKSA8LSB1bml0cyh4KQogICAgZFstMSxdCn0KYGBgCgotIFVzaW5nIHBpcGUgb3BlcmF0aW9ucywgY29tcHV0ZSBHKHIpIGZvciBlYWNoIGltYWdlIGFuZCBzdG9yZSBpdCBpbnRvIGBwYXJ0aWNsZXNfZ29mcmAuIAogICAgLSBXZSB3YW50IHRvIGNvbXB1dGUgRyhyKSB1cCB0byA1MDAgbm0gYnkgc3RlcCBvZiAyIG5tLiBNYWtlIHN1cmUgeCwgeSwgZHIgYW5kIFJtYXggYXJlIGdpdmVuIHdpdGggdGhlIHNhbWUgdW5pdC4KICAgIC0gVGhlbiwgY29tcHV0ZSB0aGUgYXZlcmFnZSBHKHIpIGZvciBlYWNoIHNhbXBsZS4KICAgIC0gSm9pbiBgcGFydGljbGVzX2dvZnJgIHdpdGggYHNhbXBsZXNgIHRvIHJldHJpZXZlIHRoZSBzYW1wbGVzIGluZm9ybWF0aW9uCgpgYGB7ciBpbmNsdWRlPXBhcmFtcyRzb2x1dGlvbiwgd2FybmluZyA9IEZBTFNFLCBtZXNzYWdlPUZBTFNFfQpwYXJ0aWNsZXNfZ29mciA8LSBwYXJ0aWNsZXMgJT4lIAogICAgbXV0YXRlKHggPSBzZXRfdW5pdHMoeCwibm0iKSwKICAgICAgICAgICB5ID0gc2V0X3VuaXRzKHksIm5tIikKICAgICAgICAgICApICU+JSAKICAgIG5lc3QoZGF0YSA9IC1jKHNhbXBsZSwgbnVtYmVyKSkgJT4lIAogICAgbXV0YXRlKEdvZlIgPSBtYXAoZGF0YSwgfmdvZnIoLiR4LCAuJHksIGRyPTIsIFJtYXg9NTAwKSkpICU+JSAKICAgIHVubmVzdChHb2ZSKSAlPiUgCiAgICBncm91cF9ieShzYW1wbGUsIHIpICU+JSAKICAgIHN1bW1hcml6ZShnb2ZyPW1lYW4oZ29mcikpICU+JSAKICAgIGlubmVyX2pvaW4oc2FtcGxlcykKYGBgCgotIEZpbmQgdGhlIGJlc3Qgd2F5IHRvIHJlcHJlc2VudCBHKHIpIGZvciBhbGwgc2FtcGxlcywgdGhhdCBhbGxvd3Mgc2VlaW5nIHRoZSBldm9sdXRpb24gd2l0aCBhbGwgcGFyYW1ldGVycy4KCmBgYHtyIGluY2x1ZGU9cGFyYW1zJHNvbHV0aW9uLCB3YXJuaW5nID0gRkFMU0UsIG1lc3NhZ2U9RkFMU0V9CnBhcnRpY2xlc19nb2ZyICU+JSAKICAgIGdncGxvdChhZXMoeD1yLCAKICAgICAgICAgICAgICAgeT1nb2ZyLCAKICAgICAgICAgICAgICAgY29sb3I9ZmFjdG9yKHRpbWUpKSkrCiAgICAgICAgZ2VvbV9zbW9vdGgobWV0aG9kPSJsb2VzcyIsIGFscGhhPS41LCBzcGFuPS4xNSwgc2U9RkFMU0UpKwogICAgICAgIGdlb21fbGluZShhbHBoYT0uMikrCiAgICAgICAgZXhwYW5kX2xpbWl0cyh4ID0gMCwgeT0wKSsKICAgICAgICBmYWNldF9ncmlkKFR+cGFzdGUoc3ViX3RoaWNrLHN1Yl9hZ2UpLCBzY2FsZXM9ImZyZWVfeSIpKwogICAgICAgIHRoZW1lKGxlZ2VuZC5wb3NpdGlvbiA9ICJ0b3AiKSsKICAgICAgICBsYWJzKHggICAgID0gInIiLAogICAgICAgICAgICAgeSAgICAgPSAiRyhyKSIsCiAgICAgICAgICAgICBjb2xvciA9ICJUaW1lIFttaW5dIikKYGBgCg==